package com.hivclassifier;

import java.util.HashSet;

import weka.core.Attribute;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;

import com.hivclassifier.models.HivClassModel;
import com.hivclassifier.models.HivClassModel.CoreceptorEnums;

public class Ccr5FeaturesInstances extends Instances {

	private static final long serialVersionUID = -3214381085432428887L;

	private Attribute chargeRuleAttribute;
	private Attribute numberOfGapsAttribute;
	private Attribute netChargeAttribute;
	private Attribute geneticDistanceToConsensusAttribute;

	private int chargeRuleAttributePosition = 41,
			numberOfGapsAttributePosition = 42,
			netChargeAttributePosition = 43,
			geneticDistanceToConsensusAttributePosition = 44, 
			classId = 45;

	public Ccr5FeaturesInstances(Instances instances) {
		super(instances);

		appendAttributes(true);
		delete();

		appendInstances(instances, true);
	}

	public Ccr5FeaturesInstances(Instances instances, boolean doWeKnowClass) {
		super(instances);

		appendAttributes(doWeKnowClass);
		delete();

		appendInstances(instances, doWeKnowClass);
	}

	public void appendAttributes(boolean doWeKnowClass) {

		if (doWeKnowClass) {
			deleteAttributeAt(41);
		}

		FastVector chargeRuleValues = new FastVector(2);
		chargeRuleValues.addElement(CoreceptorEnums.CXCR4.name());
		chargeRuleValues.addElement(CoreceptorEnums.CCR5.name());

		chargeRuleAttribute = new Attribute("chargeRule", chargeRuleValues);
		numberOfGapsAttribute = new Attribute("numberOfGaps");
		netChargeAttribute = new Attribute("netCharge");
		geneticDistanceToConsensusAttribute = new Attribute(
				"geneticDistanceToConsensus");

		insertAttributeAt(chargeRuleAttribute, chargeRuleAttributePosition);
		insertAttributeAt(numberOfGapsAttribute, numberOfGapsAttributePosition);
		insertAttributeAt(netChargeAttribute, netChargeAttributePosition);
		insertAttributeAt(geneticDistanceToConsensusAttribute,
				geneticDistanceToConsensusAttributePosition);

		FastVector classValues = new FastVector(2);
		classValues.addElement(CoreceptorEnums.CXCR4.name());
		classValues.addElement(CoreceptorEnums.DUAL.name());
		classValues.addElement(CoreceptorEnums.CCR5.name());
		Attribute classAttribute = new Attribute("class", classValues);
		if (classIndex() == -1) {
			insertAttributeAt(classAttribute, classId);
		}

		setClass(classAttribute);
		setClassIndex(classId);
	}

	public void appendInstances(Instances instances, boolean doWeKnowClass) {
		
		Instances appendedInstances = new Instances(this);
		
		Instance instance, appendedInstance;
		int numInstances = instances.numInstances();

		int instanceIndex = 0;
		HivClassModel model;

		String attributes[];

		HashSet<String> listOfNewAttributes = new HashSet<String>();
		
		for (int i = 0; i < 41; i++) {

			listOfNewAttributes = new HashSet<String>();
			
			for (instanceIndex = 0; instanceIndex < numInstances(); instanceIndex++) {
				instance = appendedInstances.instance(instanceIndex);
				attributes = instance.toString().replace("',", "").replace("'", "").split(",");
				listOfNewAttributes.add(attributes[i]);
			}
			
			for (instanceIndex = 0; instanceIndex < numInstances; instanceIndex++) {
				instance = instances.instance(instanceIndex);
				attributes = instance.toString().replace("',", "").replace("'", "").split(",");
				listOfNewAttributes.add(attributes[i]);
			}
			
			FastVector attributeValuesVector = new FastVector(listOfNewAttributes.size());
			for (String attributeValue : listOfNewAttributes) {
				attributeValuesVector.addElement(attributeValue);
			}
			
			deleteAttributeAt(i);
			
			switch (i) {
			case 0:
				insertAttributeAt(new Attribute("Name", attributeValuesVector), i);
				break;
			default:
				insertAttributeAt(new Attribute("p" + i, attributeValuesVector), i);
			}
		}
		appendedInstances.delete();

		for (instanceIndex = 0; instanceIndex < numInstances; instanceIndex++) {
			
			instance = instances.instance(instanceIndex);
			
			appendedInstance = new Instance(instance.numAttributes() + 4 + (doWeKnowClass ? 0 : 1));
			appendedInstance.setDataset(this);
			
			attributes = instance.toString().replace("',", "").replace("'", "").split(",");
			
			for (int i = 0; i < 41; i++) {
				appendedInstance.setValue(i, attributes[i]);
			}
			
			model = new HivClassModel(instance);
			
			appendedInstance.setValue(chargeRuleAttributePosition, model.chargeRule ? CoreceptorEnums.CXCR4.name() : CoreceptorEnums.CCR5.name());
			appendedInstance.setValue(numberOfGapsAttributePosition, model.numberOfGaps);
			appendedInstance.setValue(netChargeAttributePosition, model.netCharge);
			appendedInstance.setValue(geneticDistanceToConsensusAttributePosition, model.gDFromConsSeq);

			if (doWeKnowClass) {
				appendedInstance.setClassValue(String.valueOf(attributes[41]).toUpperCase());
			}
			
			add(appendedInstance);
		}
	}
}
